In [1]:
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
import matplotlib.image as mpimg
#import seaborn as sns
%matplotlib inline

#np.random.seed(2)

from sklearn.model_selection import train_test_split
from sklearn.metrics import confusion_matrix
import itertools

from keras.utils.np_utils import to_categorical 
from keras.models import Model
from keras.layers import Dense, Dropout, Flatten, Conv2D, MaxPooling2D, Input
from keras.optimizers import RMSprop
from keras.preprocessing.image import ImageDataGenerator
from keras.callbacks import ReduceLROnPlateau
from keras import backend as K

import os
os.environ['TF_CPP_MIN_LOG_LEVEL'] = '2' 


#sns.set(style='white', context='notebook', palette='deep')


/public/anaconda3/lib/python3.6/site-packages/h5py/__init__.py:36: FutureWarning: Conversion of the second argument of issubdtype from `float` to `np.floating` is deprecated. In future, it will be treated as `np.float64 == np.dtype(float).type`.
  from ._conv import register_converters as _register_converters
Using TensorFlow backend.

In [2]:
train = pd.read_csv("train.csv")
test = pd.read_csv("test.csv")

In [3]:
y_train = train['label']
X_train = train.drop(labels = ["label"],axis = 1) 
X_train = X_train / 255.0
test = test / 255.0
X_train = X_train.values.reshape(-1,28,28,1)
test = test.values.reshape(-1,28,28,1)
y_train = to_categorical(y_train, num_classes = 10)

In [4]:
random_seed = 2
X_train, X_val, Y_train, Y_val = train_test_split(X_train, y_train, test_size = 0.1, random_state=random_seed)

In [5]:
Y_train.shape


Out[5]:
(37800, 10)

In [6]:
def build_nn(input_shape, output_shape):
    input_tensor = Input(shape=input_shape)
    out = Conv2D(filters = 32, kernel_size = (5,5),padding = 'Same', activation ='relu')(input_tensor)
    out = Conv2D(filters = 32, kernel_size = (5,5),padding = 'Same', activation ='relu')(out)
    out = MaxPooling2D(pool_size=(2,2))(out)
    out = Dropout(0.25)(out)
    
    out = Conv2D(filters = 64, kernel_size = (3,3),padding = 'Same', activation ='relu')(out)
    out = Conv2D(filters = 64, kernel_size = (3,3),padding = 'Same', activation ='relu')(out)
    out = MaxPooling2D(pool_size=(2,2), strides=(2,2))(out)
    out = Dropout(0.25)(out)

    out = Flatten()(out)
    out = Dense(256, activation = "relu")(out)
    out = Dropout(0.5)(out)
    output_tensor = Dense(output_shape, activation = "softmax")(out)
    return input_tensor, output_tensor

In [8]:
input_shape = X_train[0].shape
output_shape = 10
input_tensor, output_tensor = build_nn(input_shape, output_shape)
model = Model(inputs=input_tensor, outputs=output_tensor)

optimizer = RMSprop(lr=0.001, rho=0.9, epsilon=1e-08, decay=0.0)
model.compile(optimizer = optimizer , loss = "categorical_crossentropy", metrics=["accuracy"])
learning_rate_reduction = ReduceLROnPlateau(monitor='val_acc', patience=3, verbose=1, factor=0.5, min_lr=0.00001)

datagen = ImageDataGenerator(
        featurewise_center=False,  # set input mean to 0 over the dataset
        samplewise_center=False,  # set each sample mean to 0
        featurewise_std_normalization=False,  # divide inputs by std of the dataset
        samplewise_std_normalization=False,  # divide each input by its std
        zca_whitening=False,  # apply ZCA whitening
        rotation_range=10,  # randomly rotate images in the range (degrees, 0 to 180)
        zoom_range = 0.1, # Randomly zoom image 
        width_shift_range=0.1,  # randomly shift images horizontally (fraction of total width)
        height_shift_range=0.1,  # randomly shift images vertically (fraction of total height)
        horizontal_flip=False,  # randomly flip images
        vertical_flip=False)  # randomly flip images
datagen.fit(X_train)
print(model.summary())


_________________________________________________________________
Layer (type)                 Output Shape              Param #   
=================================================================
input_1 (InputLayer)         (None, 28, 28, 1)         0         
_________________________________________________________________
conv2d_1 (Conv2D)            (None, 28, 28, 32)        832       
_________________________________________________________________
conv2d_2 (Conv2D)            (None, 28, 28, 32)        25632     
_________________________________________________________________
max_pooling2d_1 (MaxPooling2 (None, 14, 14, 32)        0         
_________________________________________________________________
dropout_1 (Dropout)          (None, 14, 14, 32)        0         
_________________________________________________________________
conv2d_3 (Conv2D)            (None, 14, 14, 64)        18496     
_________________________________________________________________
conv2d_4 (Conv2D)            (None, 14, 14, 64)        36928     
_________________________________________________________________
max_pooling2d_2 (MaxPooling2 (None, 7, 7, 64)          0         
_________________________________________________________________
dropout_2 (Dropout)          (None, 7, 7, 64)          0         
_________________________________________________________________
flatten_1 (Flatten)          (None, 3136)              0         
_________________________________________________________________
dense_1 (Dense)              (None, 256)               803072    
_________________________________________________________________
dropout_3 (Dropout)          (None, 256)               0         
_________________________________________________________________
dense_2 (Dense)              (None, 10)                2570      
=================================================================
Total params: 887,530
Trainable params: 887,530
Non-trainable params: 0
_________________________________________________________________
None

In [9]:
history = model.fit(X_train, Y_train, epochs=30, batch_size=256, validation_data=(X_val, Y_val))


Train on 37800 samples, validate on 4200 samples
Epoch 1/30
37800/37800 [==============================] - 7s 186us/step - loss: 0.3768 - acc: 0.8829 - val_loss: 0.0855 - val_acc: 0.9702
Epoch 2/30
37800/37800 [==============================] - 3s 71us/step - loss: 0.0861 - acc: 0.9736 - val_loss: 0.0603 - val_acc: 0.9810
Epoch 3/30
37800/37800 [==============================] - 3s 70us/step - loss: 0.0609 - acc: 0.9810 - val_loss: 0.0404 - val_acc: 0.9879
Epoch 4/30
37800/37800 [==============================] - 3s 71us/step - loss: 0.0497 - acc: 0.9854 - val_loss: 0.0647 - val_acc: 0.9829
Epoch 5/30
37800/37800 [==============================] - 3s 71us/step - loss: 0.0410 - acc: 0.9875 - val_loss: 0.0565 - val_acc: 0.9852
Epoch 6/30
37800/37800 [==============================] - 3s 71us/step - loss: 0.0356 - acc: 0.9888 - val_loss: 0.0332 - val_acc: 0.9910
Epoch 7/30
37800/37800 [==============================] - 3s 71us/step - loss: 0.0296 - acc: 0.9906 - val_loss: 0.0338 - val_acc: 0.9912
Epoch 8/30
37800/37800 [==============================] - 3s 71us/step - loss: 0.0267 - acc: 0.9918 - val_loss: 0.0341 - val_acc: 0.9912
Epoch 9/30
37800/37800 [==============================] - 3s 71us/step - loss: 0.0259 - acc: 0.9916 - val_loss: 0.0286 - val_acc: 0.9921
Epoch 10/30
37800/37800 [==============================] - 3s 71us/step - loss: 0.0237 - acc: 0.9929 - val_loss: 0.0369 - val_acc: 0.9917
Epoch 11/30
37800/37800 [==============================] - 3s 71us/step - loss: 0.0207 - acc: 0.9932 - val_loss: 0.0399 - val_acc: 0.9919
Epoch 12/30
37800/37800 [==============================] - 3s 71us/step - loss: 0.0207 - acc: 0.9935 - val_loss: 0.0284 - val_acc: 0.9924
Epoch 13/30
37800/37800 [==============================] - 3s 71us/step - loss: 0.0191 - acc: 0.9940 - val_loss: 0.0295 - val_acc: 0.9936
Epoch 14/30
37800/37800 [==============================] - 3s 72us/step - loss: 0.0165 - acc: 0.9948 - val_loss: 0.0324 - val_acc: 0.9936
Epoch 15/30
37800/37800 [==============================] - 3s 71us/step - loss: 0.0160 - acc: 0.9950 - val_loss: 0.0387 - val_acc: 0.9919
Epoch 16/30
37800/37800 [==============================] - 3s 71us/step - loss: 0.0153 - acc: 0.9950 - val_loss: 0.0318 - val_acc: 0.9921
Epoch 17/30
37800/37800 [==============================] - 3s 71us/step - loss: 0.0139 - acc: 0.9957 - val_loss: 0.0333 - val_acc: 0.9929
Epoch 18/30
37800/37800 [==============================] - 3s 71us/step - loss: 0.0139 - acc: 0.9955 - val_loss: 0.0268 - val_acc: 0.9943
Epoch 19/30
37800/37800 [==============================] - 3s 71us/step - loss: 0.0140 - acc: 0.9955 - val_loss: 0.0344 - val_acc: 0.9924
Epoch 20/30
37800/37800 [==============================] - 3s 71us/step - loss: 0.0140 - acc: 0.9956 - val_loss: 0.0330 - val_acc: 0.9943
Epoch 21/30
37800/37800 [==============================] - 3s 71us/step - loss: 0.0137 - acc: 0.9961 - val_loss: 0.0352 - val_acc: 0.9933
Epoch 22/30
37800/37800 [==============================] - 3s 71us/step - loss: 0.0125 - acc: 0.9957 - val_loss: 0.0412 - val_acc: 0.9921
Epoch 23/30
37800/37800 [==============================] - 3s 71us/step - loss: 0.0126 - acc: 0.9961 - val_loss: 0.0284 - val_acc: 0.9926
Epoch 24/30
37800/37800 [==============================] - 3s 71us/step - loss: 0.0115 - acc: 0.9964 - val_loss: 0.0298 - val_acc: 0.9936
Epoch 25/30
37800/37800 [==============================] - 3s 71us/step - loss: 0.0101 - acc: 0.9965 - val_loss: 0.0324 - val_acc: 0.9943
Epoch 26/30
37800/37800 [==============================] - 3s 71us/step - loss: 0.0126 - acc: 0.9962 - val_loss: 0.0403 - val_acc: 0.9926
Epoch 27/30
37800/37800 [==============================] - 3s 71us/step - loss: 0.0106 - acc: 0.9970 - val_loss: 0.0280 - val_acc: 0.9948
Epoch 28/30
37800/37800 [==============================] - 3s 71us/step - loss: 0.0105 - acc: 0.9967 - val_loss: 0.0334 - val_acc: 0.9938
Epoch 29/30
37800/37800 [==============================] - 3s 71us/step - loss: 0.0119 - acc: 0.9967 - val_loss: 0.0272 - val_acc: 0.9936
Epoch 30/30
37800/37800 [==============================] - 3s 71us/step - loss: 0.0104 - acc: 0.9968 - val_loss: 0.0363 - val_acc: 0.9943

In [12]:
epochs = 30
batch_size = 128
history = model.fit_generator(datagen.flow(X_train,Y_train, batch_size=batch_size),
                              epochs = epochs, validation_data = (X_val,Y_val),
                              verbose = 2, steps_per_epoch=X_train.shape[0] // batch_size
                              , callbacks=[learning_rate_reduction])


Epoch 1/30
 - 7s - loss: 0.0835 - acc: 0.9769 - val_loss: 0.0231 - val_acc: 0.9921
Epoch 2/30
 - 6s - loss: 0.0705 - acc: 0.9806 - val_loss: 0.0253 - val_acc: 0.9931
Epoch 3/30
 - 6s - loss: 0.0632 - acc: 0.9823 - val_loss: 0.0405 - val_acc: 0.9929
Epoch 4/30
 - 6s - loss: 0.0631 - acc: 0.9832 - val_loss: 0.0381 - val_acc: 0.9905
Epoch 5/30
 - 7s - loss: 0.0621 - acc: 0.9824 - val_loss: 0.0372 - val_acc: 0.9910
Epoch 6/30
 - 7s - loss: 0.0632 - acc: 0.9833 - val_loss: 0.0284 - val_acc: 0.9924

Epoch 00006: ReduceLROnPlateau reducing learning rate to 0.0005000000237487257.
Epoch 7/30
 - 6s - loss: 0.0495 - acc: 0.9867 - val_loss: 0.0259 - val_acc: 0.9938
Epoch 8/30
 - 7s - loss: 0.0457 - acc: 0.9870 - val_loss: 0.0244 - val_acc: 0.9940
Epoch 9/30
 - 7s - loss: 0.0449 - acc: 0.9883 - val_loss: 0.0249 - val_acc: 0.9936
Epoch 10/30
 - 6s - loss: 0.0471 - acc: 0.9876 - val_loss: 0.0233 - val_acc: 0.9943
Epoch 11/30
 - 6s - loss: 0.0465 - acc: 0.9878 - val_loss: 0.0271 - val_acc: 0.9924
Epoch 12/30
 - 6s - loss: 0.0441 - acc: 0.9878 - val_loss: 0.0221 - val_acc: 0.9940
Epoch 13/30
 - 6s - loss: 0.0419 - acc: 0.9881 - val_loss: 0.0297 - val_acc: 0.9936
Epoch 14/30
 - 6s - loss: 0.0438 - acc: 0.9882 - val_loss: 0.0282 - val_acc: 0.9929

Epoch 00014: ReduceLROnPlateau reducing learning rate to 0.0002500000118743628.
Epoch 15/30
 - 6s - loss: 0.0379 - acc: 0.9893 - val_loss: 0.0234 - val_acc: 0.9948
Epoch 16/30
 - 7s - loss: 0.0374 - acc: 0.9896 - val_loss: 0.0244 - val_acc: 0.9948
Epoch 17/30
 - 7s - loss: 0.0345 - acc: 0.9902 - val_loss: 0.0197 - val_acc: 0.9957
Epoch 18/30
 - 6s - loss: 0.0393 - acc: 0.9892 - val_loss: 0.0231 - val_acc: 0.9945
Epoch 19/30
 - 6s - loss: 0.0341 - acc: 0.9901 - val_loss: 0.0227 - val_acc: 0.9950
Epoch 20/30
 - 6s - loss: 0.0357 - acc: 0.9900 - val_loss: 0.0220 - val_acc: 0.9950
Epoch 21/30
 - 6s - loss: 0.0369 - acc: 0.9899 - val_loss: 0.0200 - val_acc: 0.9955

Epoch 00021: ReduceLROnPlateau reducing learning rate to 0.0001250000059371814.
Epoch 22/30
 - 6s - loss: 0.0317 - acc: 0.9914 - val_loss: 0.0209 - val_acc: 0.9957
Epoch 23/30
 - 6s - loss: 0.0376 - acc: 0.9902 - val_loss: 0.0214 - val_acc: 0.9948
Epoch 24/30
 - 6s - loss: 0.0326 - acc: 0.9910 - val_loss: 0.0224 - val_acc: 0.9943

Epoch 00024: ReduceLROnPlateau reducing learning rate to 6.25000029685907e-05.
Epoch 25/30
 - 6s - loss: 0.0310 - acc: 0.9910 - val_loss: 0.0212 - val_acc: 0.9943
Epoch 26/30
 - 7s - loss: 0.0281 - acc: 0.9918 - val_loss: 0.0217 - val_acc: 0.9950
Epoch 27/30
 - 7s - loss: 0.0325 - acc: 0.9915 - val_loss: 0.0203 - val_acc: 0.9955

Epoch 00027: ReduceLROnPlateau reducing learning rate to 3.125000148429535e-05.
Epoch 28/30
 - 6s - loss: 0.0301 - acc: 0.9915 - val_loss: 0.0192 - val_acc: 0.9952
Epoch 29/30
 - 7s - loss: 0.0296 - acc: 0.9918 - val_loss: 0.0198 - val_acc: 0.9950
Epoch 30/30
 - 6s - loss: 0.0278 - acc: 0.9921 - val_loss: 0.0198 - val_acc: 0.9950

Epoch 00030: ReduceLROnPlateau reducing learning rate to 1.5625000742147677e-05.

Evaluate


In [ ]:

Predict


In [10]:
results = model.predict(test)
results = np.argmax(results,axis = 1)
results = pd.Series(results,name="Label")
submission = pd.concat([pd.Series(range(1,28001),name = "ImageId"),results],axis = 1)
submission.to_csv("submissions.csv",index=False)

In [ ]: